home *** CD-ROM | disk | FTP | other *** search
- /*
- * Program: Operating system dependent routines - Ultrix 4.1
- *
- * Author: Michael Seibel
- * Networks and Distributed Computing
- * Computing & Communications
- * University of Washington
- * Administration Building, AG-44
- * Seattle, WA 98195
- * Internet: mikes@cac.washington.edu
- *
- * Date: 6 Jan 1992
- * Last Edited: 11 May 1992
- *
- * Copyright 1991 by the University of Washington
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appears in all copies and that both the
- * above copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington not be
- * used in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. This software is made
- * available "as is", and
- * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
- * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
- * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
- * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Notes:
- *
- * SGI IRIX 4.0.1 port by:
- * johnb@edge.cis.mcmaster.ca, 2 April 1992
- *
- * Dynix/PTX port by:
- * Donn Cave, UCS/UW, 15 April 1992
- *
- *
- */
-
- #include <stdio.h>
- #include <errno.h>
- #include <setjmp.h>
- #include <time.h>
- #include <pwd.h>
-
- #include "osdep.h"
- #include "estruct.h"
- #include "edef.h"
- #include "pico.h"
-
- #ifdef POSIX
- #include <termios.h>
-
- struct termios nstate,
- ostate;
- #else
- #if defined(sv3) || defined(sgi) || defined(ISC)
- #include <termio.h>
-
- struct termio nstate,
- ostate;
-
- #else
- struct sgttyb ostate; /* saved tty state */
- struct sgttyb nstate; /* values for editor mode */
- struct tchars otchars; /* Saved terminal special character set */
- struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- /* A lot of nothing */
- #endif /* sv3 || sgi */
- #endif /* POSIX */
-
- extern int rtfrmshell(); /* return from suspended shell */
-
- jmp_buf alrm_state; /* stack env to handle SIGALRM */
-
-
- #if defined(nxt) || defined(aix) || defined(POSIX)
- #define SIGTYPE void
- #else
- #define SIGTYPE int
- #endif
-
- SIGTYPE do_hup_signal();
- SIGTYPE do_alarm_signal();
- #ifdef TIOCGWINSZ
- SIGTYPE winch_handler();
- #endif
-
- #ifdef ISC
- SIGTYPE do_int_signal();
- void (*save_sigint)();
- #endif
-
-
- /*
- * This function is called once to set up the terminal device streams.
- */
- ttopen()
- {
- if(Pmaster == NULL){
- #ifdef POSIX
- tcgetattr (0, &ostate);
- tcgetattr (0, &nstate);
- nstate.c_lflag &= ~(ISIG | ICANON | ECHO);
- nstate.c_iflag &= ~ICRNL;
- nstate.c_oflag &= ~(ONLCR | OPOST);
- nstate.c_cc[VMIN] = 1;
- nstate.c_cc[VTIME] = 0;
- tcsetattr (0, TCSADRAIN, &nstate);
- #else
- #if defined(sv3) || defined(sgi) || defined (ISC)
- (void) ioctl(0, TCGETA, &ostate);
- (void) ioctl(0, TCGETA, &nstate); /** again! **/
-
- nstate.c_lflag &= ~(ICANON | ISIG | ECHO); /* noecho raw mode */
- nstate.c_oflag &= ~(OPOST | ONLCR);
- nstate.c_iflag &= ~INLCR;
-
- nstate.c_cc[VMIN] = '\01'; /* minimum # of chars to queue */
- nstate.c_cc[VTIME] = '\0'; /* minimum time to wait for input */
- (void) ioctl(0, TCSETA, &nstate);
- #else
- ioctl(0, TIOCGETP, &ostate); /* save old state */
- ioctl(0, TIOCGETP, &nstate); /* get base of new state */
- nstate.sg_flags |= RAW;
- nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */
- ioctl(0, TIOCSETP, &nstate); /* set mode */
-
- ioctl(0, TIOCGETC, &otchars); /* Save old characters */
- ioctl(0, TIOCSETC, &ntchars); /* put new character into K */
- #endif /* sv3 */
- #endif /* POSIX */
- }
-
- signal(SIGHUP, (SIGTYPE *)do_hup_signal); /* deal with SIGHUP */
- signal(SIGALRM, (SIGTYPE *)do_alarm_signal); /* timer for new mail */
- #ifdef TIOCGWINSZ
- signal(SIGWINCH, (SIGTYPE *)winch_handler); /* window size changes */
- #endif
- #ifndef sv3
- signal(SIGTSTP, (SIGTYPE *)SIG_DFL); /* set signals so we can */
- signal(SIGCONT, (SIGTYPE *)rtfrmshell); /* suspend & restart emacs */
- #endif
- }
-
-
-
- /*
- * This function gets called just before we go back home to the command
- * interpreter.
- */
- ttclose()
- {
- if(Pmaster){
- signal(SIGHUP, SIG_DFL);
- signal(SIGALRM, SIG_DFL);
- #ifndef sv3
- signal(SIGCONT, SIG_DFL);
- #endif
- #ifdef TIOCGWINSZ
- signal(SIGWINCH, SIG_DFL);
- #endif
- }
- else{
- #ifdef POSIX
- tcsetattr (0, TCSADRAIN, &ostate);
- #else
- #if defined(sv3) || defined(sgi) || defined(ISC)
- ioctl(0, TCSETA, &ostate);
- #else
- ioctl(0, TIOCSETP, &ostate);
- ioctl(0, TIOCSETC, &otchars);
- #endif /* sv3 || sgi */
- #endif /* POSIX */
- }
- #ifdef ISC
- ioctl(0, TCSETAW, &ostate); /* set old state */
- #endif
- }
-
-
- /*
- * Write a character to the display.
- */
- ttputc(c)
- {
- putc(c, stdout);
- }
-
-
- /*
- * Flush terminal buffer. Does real work where the terminal output is buffered
- * up. A no-operation on systems where byte at a time terminal I/O is done.
- */
- ttflush()
- {
- fflush(stdout);
- }
-
- /*
- * Read a character from the terminal, performing no editing and doing no echo
- * at all.
- */
- ttgetc()
- {
- register int c;
-
- if((c = fgetc(stdin)) == EOF){
- if(errno == EINTR) /* only one that might be OK */
- return(NODATA);
- kill(getpid(), SIGHUP); /* the only honorable thing to do */
- }
- else
- return(c & 0xff);
- }
-
-
- #if TYPEAH
- /* typahead: Check to see if any characters are already in the
- * keyboard buffer
- */
- typahead()
- {
- int x; /* holds # of pending chars */
-
- return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
- }
- #endif
-
-
- /*
- * Read in a key.
- * Do the standard keyboard preprocessing. Convert the keys to the internal
- * character set. Resolves escape sequences and returns no-op if global
- * timeout value exceeded.
- */
- GetKey()
- {
- int c;
-
- if(timeout){
- if(setjmp(alrm_state) == 0){
- alarm((unsigned)timeout);
- errno = 0;
- c = (*term.t_getchar)();
- if(errno == EINTR)
- c = NODATA;
- }
- else
- c = NODATA; /* alarm went off so go back */
-
- alarm(0); /* shut off the alarm */
- if(c == NODATA)
- return(c);
- }
- else{
- c = (*term.t_getchar)();
- }
-
- if (c == METACH) { /* Apply M- prefix */
- int status;
-
- /*
- * this code should intercept special keypad keys
- */
-
- switch(status = kbseq(&c)){
- case 0 : /* no dice */
- return(c);
- case K_PAD_UP :
- case K_PAD_DOWN :
- case K_PAD_RIGHT :
- case K_PAD_LEFT :
- case K_PAD_PREVPAGE :
- case K_PAD_NEXTPAGE :
- case K_PAD_HOME :
- return(status);
- case F1 :
- case F2 :
- case F3 :
- case F4 :
- case F5 :
- case F6 :
- case F7 :
- case F8 :
- case F9 :
- case F10 :
- case F11 :
- case F12 :
- return(status);
- case BADESC :
- default : /* punt the whole thing */
- (*term.t_beep)();
- break;
- }
- }
-
- if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
- c = CTRL | (c+'@');
-
- return (c);
-
- }
-
-
-
- /* kbseq - looks at an escape sequence coming from the keyboard and
- * compares it to a trie of known keyboard escape sequences, and
- * performs the function bound to the escape sequence.
- *
- * returns: BADESC, the escaped function, or 0 if not found.
- */
- kbseq(c)
- int *c;
- {
- register char b;
- register int first = 1;
- register struct KBSTREE *current = kpadseqs;
-
- if(kpadseqs == NULL) /* bag it */
- return(BADESC);
- while(1){
- *c = b = (*term.t_getchar)();
-
- while(current->value != b){
- if(current->left == NULL){ /* NO MATCH */
- if(first)
- return(BADESC);
- else
- return(0);
- }
- current = current->left;
- }
-
- if(current->down == NULL) /* match!!!*/
- return(current->func);
- else
- current = current->down;
-
- first = 0;
- }
- }
-
-
-
- /*
- * This is code for a planned pine feature that isn't actually in use
- * yet. It is an example of one possible way of implementing an alternate
- * editor, but maybe not the final word on how it will be done.
- * It may be that we decide to make this a configuration option (thus
- * saving a very limited resource: control-key combinations. We're
- * still considering these options...
- */
- #include <sys/wait.h>
-
-
- /*
- * alt_editor - fork off an alternate editor for mail message composition
- */
- alt_editor(f, n)
- {
- #ifdef OLDWAY
- char eb[NLINE];
- #else
- char *eb;
- #endif
- char *fn;
- char *writetmp();
- int child, pid, done = 0;
- long l;
- #if defined(POSIX) || defined(ISC)
- int stat;
- #else
- union wait stat;
- #endif
- FILE *p;
-
- #ifdef OLDWAY
- *eb = '\0';
- #endif
-
- if(Pmaster == NULL)
- return;
-
- #ifdef OLDWAY
- while(!done){
- /* which alternate editor */
- switch(mlreply("Which alternate editor ? ", eb, NLINE, TRUE)){
- case ABORT:
- return(-1);
- case HELPCH:
- emlwrite("no alternate editor help yet");
-
- /* take sleep and break out after there's help */
- sleep(3);
- break;
- case (CTRL|'L'):
- sgarbf = TRUE;
- update();
- break;
- case TRUE:
- case FALSE: /* does editor exist ? */
- if(*eb== '\0'){ /* leave silently */
- emlwrite("");
- return(-1);
- }
- #ifdef MAYBELATER
- else if(*eb != '/'){
- int status;
- char *fp, *efp;
-
- if(*eb == '~'){
- strcpy(s, "~");
- fixpath(s, 1024);
- strcat(s,"/");
- strcat(eb,"/");
- }
- else if((fp=getenv("PATH")) == NULL){
- emlwrite("Can't find editor \"%s\"", eb);
- return(-1);
- }
- else
- emlwrite("got path: %s",fp);
- while(fp){
- sprintf(s, "%s/%s", fp, eb);
- if((status=fexist(eb, "x", &l)) != FIOSUC){
- fioperr(status, eb);
- return(-1);
- }
- }
- }
- #endif
- done++;
- break;
- default:
- break;
- }
- }
- #else
- if(Pmaster->alt_ed == NULL)
- return;
-
- eb = Pmaster->alt_ed;
- #endif
-
- if((fn=writetmp(0, 1)) == NULL){ /* get temp file */
- emlwrite("Problem writing temp file for alt editor");
- return(-1);
- }
-
- if(Pmaster)
- (*Pmaster->raw_io)(0); /* turn off raw mode */
-
- if(child=fork()){ /* wait for the child to finish */
- while((pid=wait(&stat)) != child)
- ;
- }
- else{ /* spawn editor */
- if(execlp(eb, eb, fn, (char *) 0) < 0)
- exit(1);
- }
-
- if(Pmaster)
- (*Pmaster->raw_io)(1); /* turn on raw mode */
-
- /*
- * replace edited text with new text
- */
- curwp->w_bufp->b_flag &= ~BFCHG; /* make sure it gets blasted */
- bclear(curwp->w_bufp); /* blast old text */
- readin(fn, 0); /* read new text */
- unlink(fn); /* blast temp file */
-
- ttopen();
- refresh(0, 1); /* redraw */
- }
-
-
-
- /*
- * bktoshell - suspend and wait to be woken up
- */
- bktoshell() /* suspend MicroEMACS and wait to wake up */
- {
- #ifndef sv3
- int pid;
- int rtfrmshell();
- extern int vttidy();
-
- if(!(gmode&MDSSPD)){
- emlwrite("\007Unknown command: ^Z");
- return;
- }
-
- if(Pmaster){
- (*Pmaster->raw_io)(0); /* actually in pine source */
-
- movecursor(term.t_nrow, 0);
- printf("\n\n\nUse \"fg\" to return to Pine\n");
-
- signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
- signal(SIGCONT, (SIGTYPE *)rtfrmshell); /* suspend & restart emacs */
- }
- else{
- vttidy();
- }
-
- movecursor(term.t_nrow, 0);
- peeol();
- (*term.t_flush)();
-
- pid = getpid();
- kill(pid,SIGTSTP);
- #else
- #endif
- }
-
-
- /*
- * rtfrmshell - back from shell, fix modes and return
- */
- rtfrmshell()
- {
- #ifndef sv3
- if(Pmaster){
- signal(SIGCONT, SIG_DFL);
- if(Pmaster)
- (*Pmaster->raw_io)(1); /* actually in pine source */
- (*Pmaster->keybinit)(gmode&MDFKEY); /* using f-keys? */
- }
-
- ttopen();
-
- sgarbf = TRUE;
- curwp->w_flag = WFHARD;
- refresh();
- #else
- #endif
- }
-
-
-
- /*
- * do_alarm_signal - jump back in the stack to where we can handle this
- */
- SIGTYPE do_alarm_signal()
- {
- signal(SIGALRM, (SIGTYPE *)do_alarm_signal);
- longjmp(alrm_state, 1);
- }
-
- #ifdef ISC
- /*
- * do_int_signal - jump back in the stack to where we can handle this
- */
- /* I don't know how this works for other OS's! Seems like a bug, no? */
-
- SIGTYPE do_int_signal()
- {
- extern jmp_buf finstate; /* stack environment to return codes [pico.c] */
- /* This will handle SIGINT */
-
- if(0 /*for_pine*/){
- signal(SIGINT, (SIGTYPE *)do_int_signal);
- abort_composer(1,0);
- }
- }
-
- #endif
-
- /*
- * do_hup_signal - jump back in the stack to where we can handle this
- */
- SIGTYPE do_hup_signal()
- {
- extern jmp_buf got_hup;
-
- if(Pmaster){
- signal(SIGHUP, (SIGTYPE *)do_hup_signal);
- longjmp(got_hup, 1);
- }
- else{
- /*
- * if we've been interrupted and the buffer is changed,
- * save it...
- */
- if(anycb() == TRUE){ /* time to save */
- if(curbp->b_fname[0] == '\0'){ /* name it */
- strcpy(curbp->b_fname, "pico.save");
- }
- else{
- strcat(curbp->b_fname, ".save");
- }
- writeout(curbp->b_fname);
- }
- vttidy();
- exit(1);
- }
- }
-
-
- char okinfname[32] = {
- 0, 0, /* ^@ - ^G, ^H - ^O */
- 0, 0, /* ^P - ^W, ^X - ^_ */
- 0, 0x17, /* SP - ' , ( - / */
- 0xff, 0xc0, /* 0 - 7 , 8 - ? */
- 0x7f, 0xff, /* @ - G , H - O */
- 0xff, 0xe1, /* P - W , X - _ */
- 0x7f, 0xff, /* ` - g , h - o */
- 0xff, 0xe2, /* p - w , x - DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0 /* > DEL */
- };
-
-
- /*
- * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
- */
- fallowc(c)
- char c;
- {
- return(okinfname[c>>3] & 0x80>>(c&7));
- }
-
-
-
- /*
- * fexist - returns TRUE if the file exists, FALSE otherwise
- */
- fexist(file, m, l)
- char *file;
- char *m; /* files mode: r, w or rw */
- long *l;
- {
- struct stat sbuf;
-
- if(l)
- *l = 0L;
-
- if(stat(file, &sbuf) < 0){
- switch(errno){
- case ENOENT : /* File not found */
- return(FIOFNF);
- break;
- case ENAMETOOLONG : /* Name is too long */
- return(FIOLNG);
- break;
- default: /* Some other error */
- return(FIOERR);
- break;
- }
- }
-
- if(l)
- *l = sbuf.st_size;
-
- if(sbuf.st_mode & S_IFDIR)
- return(FIODIR);
-
- if(m[0] == 'r') /* read access? */
- return(((S_IREAD | 044) & sbuf.st_mode) ? FIOSUC : FIONRD);
- else if(m[0] == 'w') /* write access? */
- return(((S_IWRITE | 022) & sbuf.st_mode) ? FIOSUC : FIONWT);
- else if(m[0] == 'x') /* execute access? */
- return(((S_IEXEC | 011) & sbuf.st_mode) ? FIOSUC : FIONEX);
- return(FIOERR); /* what? */
- }
-
-
- /*
- * isdir - returns true if fn is a readable directory, false otherwise
- * silent on errors (we'll let someone else notice the problem;)).
- */
- isdir(fn, l)
- char *fn;
- long *l;
- {
- struct stat sbuf;
-
- if(l)
- *l = 0;
-
- if(stat(fn, &sbuf) < 0)
- return(0);
-
- if(l)
- *l = sbuf.st_size;
- return(sbuf.st_mode & S_IFDIR);
- }
-
-
- #if defined(nxt) || defined(dyn)
- /*
- * getcwd - NeXT uses getwd()
- */
- char *getcwd(pth)
- char *pth;
- {
- extern char *getwd();
-
- return(getwd(pth));
- }
- #endif
-
-
- /*
- * getfnames - return all file names in the given directory in a single
- * malloc'd string. n contains the number of names
- */
- char *getfnames(dn, n)
- char *dn;
- int *n;
- {
- int status;
- long l;
- char *names, *np, *p;
- struct stat sbuf;
- DIR *dirp; /* opened directory */
- #if defined(POSIX) || defined(ISC)
- struct dirent *dp;
- #else
- struct direct *dp;
- #endif
- extern char *sys_errlist[];
-
- *n = 0;
-
- if(stat(dn, &sbuf) < 0){
- switch(errno){
- case ENOENT : /* File not found */
- emlwrite("\007File not found: \"%s\"", dn);
- break;
- case ENAMETOOLONG : /* Name is too long */
- emlwrite("\007File name too long: \"%s\"", dn);
- break;
- default: /* Some other error */
- emlwrite("\007Error getting file info: \"%s\"", dn);
- break;
- }
- return(NULL);
- }
- else{
- l = sbuf.st_size;
- if(!(sbuf.st_mode & S_IFDIR)){
- emlwrite("\007Not a directory: \"%s\"", dn);
- return(NULL);
- }
- }
-
- if((names=(char *)malloc(sizeof(char)*l)) == NULL){
- emlwrite("\007Can't malloc space for file names");
- return(NULL);
- }
-
- errno = 0;
- if((dirp=opendir(dn)) == NULL){
- sprintf(s,"\007Can't open \"%s\": %s", dn, sys_errlist[errno]);
- emlwrite(s);
- free((char *)names);
- return(NULL);
- }
-
- np = names;
- while((dp = readdir(dirp)) != NULL){
- (*n)++;
- p = dp->d_name;
- while((*np++ = *p++) != '\0')
- ;
- }
-
- closedir(dirp); /* shut down */
- return(names);
- }
-
-
- /*
- * fioperr - given the error number and file name, display error
- */
- fioperr(e, f)
- int e;
- char *f;
- {
- switch(e){
- case FIOFNF: /* File not found */
- emlwrite("\007File \"%s\" not found", f);
- break;
- case FIOEOF: /* end of file */
- emlwrite("\007End of file \"%s\" reached", f);
- break;
- case FIOLNG: /* name too long */
- emlwrite("\007File name \"%s\" too long", f);
- break;
- case FIODIR: /* file is a directory */
- emlwrite("\007File \"%s\" is a directory", f);
- break;
- case FIONWT:
- emlwrite("\007Write permission denied: %s", f);
- break;
- case FIONRD:
- emlwrite("\007Read permission denied: %s", f);
- break;
- case FIONEX:
- emlwrite("\007Execute permission denied: %s", f);
- break;
- default:
- emlwrite("\007File I/O error: %s", f);
- }
- }
-
-
-
- /*
- * pfnexpand - pico's function to expand the given file name if there is
- * a leading '~'
- */
- char *pfnexpand(fn, len)
- char *fn;
- int len;
- {
- struct passwd *pw;
- struct passwd *getpwnam(), *getpwuid();
- register char *x, *y, *z;
- char name[20];
-
- if(*fn == '~') {
- for(x = fn+1, y = name; *x != '/' && *x != '\0'; *y++ = *x++);
- *y = '\0';
- if(x == fn + 1)
- pw = getpwuid(getuid());
- else
- pw = getpwnam(name);
- if(pw == NULL)
- return(NULL);
- if(strlen(pw->pw_dir) + strlen(fn) > len) {
- return(NULL);
- }
- /* make room for expanded path */
- for(z=x+strlen(x),y=fn+strlen(x)+strlen(pw->pw_dir);
- z >= x;
- *y-- = *z--);
- /* and insert the expanded address */
- for(x=fn,y=pw->pw_dir; *y != '\0'; *x++ = *y++);
- }
- return(fn);
- }
-
-
-
- /*
- * fixpath - make the given pathname into an absolute path
- */
- fixpath(name, len)
- char *name;
- int len;
- {
- register char *shft;
-
- if(*name != '/'){ /* filenames relative to ~ */
- if(Pmaster && (*name != '~' && strlen(name)+2 <= len)){
-
- for(shft = strchr(name, '\0'); shft >= name; shft--)
- shft[2] = *shft;
-
- name[0] = '~';
- name[1] = '/';
- }
-
- pfnexpand(name, len);
- }
- }
-
-
- /*
- * tmpname - return a temporary file name in the given buffer
- */
- tmpname(name)
- char *name;
- {
- sprintf(name, "/tmp/pico.%d", getpid()); /* tmp file name */
- }
-
-
- /*
- * Take a file name, and from it
- * fabricate a buffer name. This routine knows
- * about the syntax of file names on the target system.
- * I suppose that this information could be put in
- * a better place than a line of code.
- */
- makename(bname, fname)
- char bname[];
- char fname[];
- {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
-
- while (cp1!=&fname[0] && cp1[-1]!='/')
- --cp1;
- cp2 = &bname[0];
- while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
- *cp2++ = *cp1++;
- *cp2 = 0;
- }
-
-
-
- /*
- * Open a file for writing. Return TRUE if all is well, and FALSE on error
- * (cannot create).
- */
- ffwopen(fn)
- char *fn;
- {
- extern FILE *ffp;
-
- if ((ffp=fopen(fn, "w")) == NULL) {
- emlwrite("Cannot open file for writing");
- return (FIOERR);
- }
- return (FIOSUC);
- }
-
-
- /*
- * Close a file. Should look at the status in all systems.
- */
- ffclose()
- {
- extern FILE *ffp;
-
- if (fclose(ffp) != FALSE) {
- emlwrite("Error closing file");
- return(FIOERR);
- }
- return(FIOSUC);
- }
-
-
- /*
- * P_open - run the given command in a sub-shell returning a file pointer
- * from which to read the output
- *
- * note:
- * For OS's other than unix, you will have to rewrite this function.
- * Hopefully it'll be easy to exec the command into a temporary file,
- * and return a file pointer to that opened file or something.
- */
- FILE *P_open(s)
- char *s;
- {
- return(popen(s, "r"));
- }
-
-
-
- /*
- * P_close - close the given descriptor
- *
- */
- P_close(fp)
- FILE *fp;
- {
- return(pclose(fp));
- }
-
-
-
- /*
- * worthit - generic sort of test to roughly gage usefulness of using
- * optimized scrolling.
- *
- * note:
- * returns the line on the screen, l, that the dot is currently on
- */
- worthit(l)
- int *l;
- {
- int i; /* l is current line */
- unsigned below; /* below is avg # of ch/line under . */
-
- *l = doton(&i, &below);
- below = (i > 0) ? below/(unsigned)i : 0;
-
- return(below > 3);
- }
-
-
- /*
- * pico_new_mail - just checks mtime and atime of mail file and notifies user
- * if it's possible that they have new mail.
- */
- pico_new_mail()
- {
- int ret = 0;
- static time_t lastchk = 0;
- struct stat sbuf;
- char inbox[256];
-
- #ifdef ISC
- sprintf(inbox,"/usr/mail/%s", getlogin());
- #else
- sprintf(inbox,"/usr/spool/mail/%s", getlogin());
- #endif
- if(stat(inbox, &sbuf) == 0){
- ret = sbuf.st_atime <= sbuf.st_mtime &&
- (lastchk < sbuf.st_mtime && lastchk < sbuf.st_atime);
- lastchk = sbuf.st_mtime;
- return(ret);
- }
- else
- return(ret);
- }
-
-
-
- /*
- * time_to_check - checks the current time against the last time called
- * and returns true if the elapsed time is > timeout
- */
- time_to_check()
- {
- static time_t lasttime = 0L;
-
- if(!timeout)
- return(FALSE);
-
- if(time((long *) 0) - lasttime > (time_t)timeout){
- lasttime = time((long *) 0);
- return(TRUE);
- }
- else
- return(FALSE);
- }
-
-
- /*
- * sstrcasecmp - compare two pointers to strings case independently
- */
- sstrcasecmp(s1, s2)
- char **s1, **s2;
- {
- register char *a, *b;
-
- a = *s1;
- b = *s2;
- while(toupper(*a) == toupper(*b++))
- if(*a++ == '\0')
- return(0);
-
- return(toupper(*a) - toupper(*--b));
- }
-
-
- #ifdef TIOCGWINSZ
- /*
- * winch_handler - handle window change signal
- */
- SIGTYPE winch_handler()
- {
- struct winsize win;
- extern int resize_pico();
-
- signal(SIGWINCH, (SIGTYPE *)winch_handler);
-
- if (ioctl(0, TIOCGWINSZ, &win) == 0) {
- if (win.ws_col && win.ws_row)
- resize_pico(win.ws_row - 1, win.ws_col);
- }
- }
- #endif /* TIOCGWINSZ */
-